﻿using Common.Communal;
using ERP.Domain.CustomerSupplier;
using MediatR;
using SqlSugar;
using Warehouse.API.Read.App.Commands;
using Warehouse.Dto;

namespace Warehouse.API.Read.App.Handers
{
    /// <summary>
    /// 报表汇总查询处理器 - 实现 CQRS 模式中的查询处理
    /// 负责处理库存交易数据的汇总统计查询
    /// 继承 IRequestHandler 接口，实现 MediatR 的请求处理模式
    /// </summary>
    public class ReportSummaryHanders : IRequestHandler<ReportSummary, ApiResult<ApiPaging<InventorySummaryDto>>>
    {
        #region 私有字段

        /// <summary>
        /// SqlSugar 数据库客户端 - 提供高性能的数据库访问和查询功能
        /// 支持链式查询、分页、聚合等高级功能
        /// </summary>
        private readonly ISqlSugarClient _sqlSugarClient;

        #endregion

        #region 构造函数

        /// <summary>
        /// 构造函数 - 依赖注入初始化
        /// </summary>
        /// <param name="sqlSugarClient">SqlSugar 数据库客户端实例</param>
        public ReportSummaryHanders(ISqlSugarClient sqlSugarClient)
        {
            _sqlSugarClient = sqlSugarClient;
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 处理查询请求 - 实现 MediatR 的请求处理接口
        /// 执行库存交易数据的汇总统计查询，按产品名称分组计算入库、出库和结余数量
        /// </summary>
        /// <param name="request">查询请求对象 - 包含分页参数和查询条件</param>
        /// <param name="cancellationToken">取消令牌 - 用于取消长时间运行的查询操作</param>
        /// <returns>查询结果 - 包含分页数据和汇总统计信息</returns>
        public Task<ApiResult<ApiPaging<InventorySummaryDto>>> Handle(ReportSummary request, CancellationToken cancellationToken)
        {
            // 创建响应对象 - 使用统一的 API 响应格式
            var result = new ApiResult<ApiPaging<InventorySummaryDto>>
            {
                Code = EnumCode.Ok,        // 成功状态码
                Message = "查询成功"       // 成功消息
            };

            try
            {
                // 初始化分页参数 - 用于存储查询结果的分页信息
                int totalCount = 0;    // 总记录数
                int totalPage = 0;     // 总页数

                // 构建基础查询 - 使用 SqlSugar 的链式查询语法
                // 查询库存交易记录表，作为后续分组统计的基础
                var baseQuery = _sqlSugarClient.Queryable<ERP.Domain.Warehouse.InventoryTransaction>();

                // 应用查询条件 - 动态构建 WHERE 子句
                // 如果提供了产品名称，则进行模糊查询
                if (!string.IsNullOrWhiteSpace(request.ProductName))
                {
                    baseQuery = baseQuery.Where(x => x.ProductName.Contains(request.ProductName));
                }

                // 执行分组聚合查询 - 实现数据汇总统计
                // 按产品名称分组，计算每个产品的入库、出库和结余数量
                var groupedQuery = baseQuery
                    .GroupBy(x => new { x.ProductName }) // 按产品名称分组
                    .Select(x => new InventorySummaryDto
                    {
                        // 基础信息 - 使用聚合函数获取代表性值
                        ProductName = x.ProductName,                                    // 产品名称（分组键）
                        ProductNumber = SqlFunc.AggregateMax(x.ProductNumber),         // 产品编号（取最大值）
                        Specification = SqlFunc.AggregateMax(x.Specification),         // 规格型号（取最大值）
                        Unit = SqlFunc.AggregateMax(x.Unit),                           // 单位（取最大值）
                        WarehouseName = SqlFunc.AggregateMax(x.WarehouseName),         // 仓库名称（取最大值）
                        TransactionType = SqlFunc.AggregateMax(x.TransactionType),     // 交易类型（取最大值）
                        UnitPrice = SqlFunc.AggregateMax(SqlFunc.IsNull(x.UnitPrice, 0m)), // 单价（取最大值，空值处理为0）
                        Applicant = SqlFunc.AggregateMax(x.Applicant),                 // 申请人（取最大值）

                        // 入库数量统计 - 使用条件聚合函数
                        // 当交易类型以"入库"结尾时，累加数量；否则累加0
                        InQuantity = SqlFunc.AggregateSum(
                            SqlFunc.IIF(
                                SqlFunc.EndsWith(x.TransactionType, "入库"),  // 条件：交易类型以"入库"结尾
                                SqlFunc.IsNull(x.Quantity, 0m),              // 真值：数量（空值处理为0）
                                0m                                           // 假值：0
                            )
                        ),

                        // 出库数量统计 - 使用条件聚合函数
                        // 当交易类型以"出库"结尾时，累加数量；否则累加0
                        OutQuantity = SqlFunc.AggregateSum(
                            SqlFunc.IIF(
                                SqlFunc.EndsWith(x.TransactionType, "出库"),  // 条件：交易类型以"出库"结尾
                                SqlFunc.IsNull(x.Quantity, 0m),              // 真值：数量（空值处理为0）
                                0m                                           // 假值：0
                            )
                        ),

                        // 结余数量计算 - 入库数量减去出库数量
                        // 使用两个独立的聚合函数计算差值
                        BalanceQuantity = 
                            SqlFunc.AggregateSum(
                                SqlFunc.IIF(
                                    SqlFunc.EndsWith(x.TransactionType, "入库"),  // 条件：交易类型以"入库"结尾
                                    SqlFunc.IsNull(x.Quantity, 0m),              // 真值：数量（空值处理为0）
                                    0m                                           // 假值：0
                                )
                            ) -
                            SqlFunc.AggregateSum(
                                SqlFunc.IIF(
                                    SqlFunc.EndsWith(x.TransactionType, "出库"),  // 条件：交易类型以"出库"结尾
                                    SqlFunc.IsNull(x.Quantity, 0m),              // 真值：数量（空值处理为0）
                                    0m                                           // 假值：0
                                )
                            )
                    });

                // 执行分页查询 - 获取指定页的数据
                // 使用 SqlSugar 的分页功能，自动计算总记录数和总页数
                var pagedData = groupedQuery.ToPageList(
                    request.pageindex,  // 页码
                    request.pagesize,   // 页大小
                    ref totalCount,     // 总记录数（引用传递，会被修改）
                    ref totalPage       // 总页数（引用传递，会被修改）
                );

                // 构建分页响应对象
                var pagingResult = new ApiPaging<InventorySummaryDto>
                {
                    TotalPage = totalPage,      // 总页数
                    TotalCount = totalCount,    // 总记录数
                    Data = pagedData           // 当前页的数据
                };

                // 设置响应数据
                result.Data = pagingResult;
            }
            catch (Exception ex)
            {
                // 异常处理 - 返回错误响应
                result.Code = EnumCode.Fail;
                result.Message = $"查询失败: {ex.Message}";
                result.Data = null;
            }

            // 返回异步任务结果
            return Task.FromResult(result);
        }

        #endregion

        #region 私有辅助方法

        /// <summary>
        /// 验证查询参数 - 确保请求参数的有效性
        /// </summary>
        /// <param name="request">查询请求对象</param>
        /// <returns>验证结果</returns>
        private bool ValidateRequest(ReportSummary request)
        {
            // 检查请求对象是否为空
            if (request == null)
            {
                return false;
            }

            // 检查分页参数的有效性
            if (request.pageindex < 1 || request.pagesize < 1)
            {
                return false;
            }

            // 检查页大小是否超过最大限制（防止内存溢出）
            if (request.pagesize > 1000)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 构建错误响应 - 创建统一的错误响应格式
        /// </summary>
        /// <param name="errorCode">错误代码</param>
        /// <param name="errorMessage">错误信息</param>
        /// <returns>错误响应对象</returns>
        private ApiResult<ApiPaging<InventorySummaryDto>> BuildErrorResponse(EnumCode errorCode, string errorMessage)
        {
            return new ApiResult<ApiPaging<InventorySummaryDto>>
            {
                Code = errorCode,
                Message = errorMessage,
                Data = null
            };
        }

        #endregion
    }
}
